#include "my_adc.h"
#include "sys_param.h"

volatile uint32_t u32AdcRestult;

MY_ADC_PARAM_t adc_data;



///< 端口初始化
static void adc_port_init(void)
{    
    ///< 开启GPIO外设时钟
    SYSCTRL_PeriphClkEnable(SYSCTRL_PERIRESET_PA);
    
    ///< 模拟端口输入信号初始化
    GPIO_PA01_ANALOG_SET();  

    GPIO_PA02_ANALOG_SET();
}

///< ADC模块 初始化
static void app_adc_init(void)
{
    stc_adc_cfg_t   stcAdcCfg={0};
    
    /* 第一步：开启ADC/BGR 外设时钟 */
    SYSCTRL_PeriphClkEnable(SYSCTRL_PERIRESET_ADC);
    
    /* 第三步：ADC 初始化配置 */
    stcAdcCfg.u32ClkDiv           = ADC_CLOCK_PCLK_DIV128;     ///< 采样分频-128
    stcAdcCfg.u32SampCycleSel     = ADC_SAMPLINGTIME_12CYCLE;  ///< 采样周期数-12
    stcAdcCfg.u32RefVolSel        = ADC_REF_VOLTAGE_AVCC;      ///< 参考电压选择-AVCC
    stcAdcCfg.u32InputSource      = ADC_EXINPUT_PA02;  ///< 输入信号选择-PA01
    //stcAdcCfg.u32ExtTriggerSource = ADC_EXTTRIGGER_PB03;       ///< 外部触发信号来自-PB03
    ADC_Init(ADC, &stcAdcCfg);
    
    /* 第四步：清除中断标志位 */
    ADC_ClearFlag_EOC(ADC);
    
    /* 第四步：配置中断 */
    ADC_EnableIT_EOC(ADC);      ///< 使能EOC中断
    EnableNvic(ADC_IRQn, IrqLevel3, TRUE);  ///< 使能内核NVIC
}

 ///< ADC 中断服务程序
void Adc_IRQHandler(void)
{        
    /* 判断是否产生EOS标志 */
    if(TRUE == ADC_IsActiveFlag_EOC(ADC))
    {
        ADC_ClearFlag_EOC(ADC);              ///< 清除EOC中断标志位
        u32AdcRestult = ADC_GetResult(ADC);  ///< 获取采样值
    }
}


// void ADC_SetInputSource(ADC_TypeDef *ADCx, uint32_t u32AdcSampInput)

void adc_pa1_read(void)
{

    ADC_SetInputSource(ADC, ADC_EXINPUT_PA01);
    adc_data.port_select = 1;
        ///< 开启单次转换
    ADC_StartSingleConversion(ADC);  ///< 产生EOC标志

}

void adc_pa2_read(void)
{

    ADC_SetInputSource(ADC, ADC_EXINPUT_PA02);
    adc_data.port_select = 2;
        ///< 开启单次转换
    ADC_StartSingleConversion(ADC);  ///< 产生EOC标志

}

//************冒泡排序法 */
void Bubble_Sort(int *arr, int size)  
{  
    int i, j, tmp;  
    int swap_times = 0;
    
    for (i = 0; i < size - 1; i++) {  
        for (j = 0; j < size - i - 1; j++) {  
            if (arr[j] > arr[j+1]) {  
                tmp = arr[j];  
                arr[j] = arr[j+1];  
                arr[j+1] = tmp; 
                swap_times ++; 
            }
        }  
    }  
    // printf(" \r\n bubble_sort_02 swap_times:%d \r\n", swap_times);
} 



/**************************
 * 10 ms 进入一次
 *  10位ADC采样
 *   VCC = 3.0V  -----1024
 *  PA2 约为 0.3v ----大约为100 adc_val =100;  作为充满识别脚
 *  PA1 --------------------------------------作为开始充电识别脚。
 *                                          当机器刚接触底座时，未开启充电使能时，能识别到该脚位adc值较大0.8v，
 *                                          当开启充电后，该脚位adc值较低，随着充电电流的变小而变小
 * 充电电流 160ma时， pa2=37，pa1=15
 * 充电电流 100ma时， pa2=23，pa1=9
 * 充电电流 0ma时，   pa2=2--3，pa1=0
 *  
 * 
 * 
 * 设备不在线时，两个adc值都为0
 * 
 * 
 * 
 ********************/
#define DEV_ONLINE_MIN_ADC_VAL      (100)//(240)
#define CHARGE_MIN_ADC_VAL          (10)

static int print_delay;

void charge_state_check(void)
{
    static int charging_online_cnt = 0;
    static int charg_finish_cnt = 0;
    static int charg_offlie_cnt = 0;

    
    if(1 == adc_data.port_select){
         
        // adc_pa1_read();
        adc_data.pa1_index ++;
        adc_data.pa1_index %=MAX_ADC_CNT;
        adc_data.pa1_dac_buff[adc_data.pa1_index] = u32AdcRestult;

        //以pa1 脚位的adc作为充电判断， 设备刚接入时，该脚位adc较大，开始充电后，改脚位
        Bubble_Sort(adc_data.pa1_dac_buff, MAX_ADC_CNT);

        if(adc_data.pa1_dac_buff[MAX_ADC_CNT/2] > DEV_ONLINE_MIN_ADC_VAL){
            charging_online_cnt++;
            if(charging_online_cnt == 10){
                charg_offlie_cnt = 0;

                if(IDLE_STA == get_sys_sta()){
                    set_sys_sta(CHARING_FIRST_1MIN_STA);
                    charg_finish_cnt = 0;
                }
            }
        }
        else
        {
            charging_online_cnt = 0;
        }
        // else{
        //     charg_offlie_cnt ++;
        //     if(charg_offlie_cnt == 5){
        //         charging_online_cnt = 0;
        //         if(IDLE_STA != get_sys_sta()){
        //             set_sys_sta(IDLE_STA);
        //         }
        //     }
        // }
        
        if(adc_data.pa1_index == 19){
//         printf("\n\r pa1:|%d|  \n\r", adc_data.pa1_dac_buff[MAX_ADC_CNT/2]);
        }
        adc_pa2_read();
    }
#if 1
    else{     
        adc_data.pa2_index ++;
        adc_data.pa2_index %=MAX_ADC_CNT;
        adc_data.pa2_dac_buff[adc_data.pa2_index] = u32AdcRestult; 
        // if(IDLE_STA == get_sys_sta()){
        //     adc_pa1_read();
        // }
        // else{
        //     adc_pa2_read();
        // }

        if(adc_data.pa2_index == 19){
//             printf("\n\r pa2:|%d|,charge_cnt:%d  \n\r", adc_data.pa2_dac_buff[MAX_ADC_CNT/2], charg_finish_cnt);
        }

            Bubble_Sort(adc_data.pa2_dac_buff, MAX_ADC_CNT);

            if(adc_data.pa2_dac_buff[MAX_ADC_CNT/2] > CHARGE_MIN_ADC_VAL){
                // charging_online_cnt++;
                // if(charging_online_cnt == 5){
                //     charg_offlie_cnt = 0;

                //     if(IDLE_STA == get_sys_sta()){
                //         set_sys_sta(CHARING_FIRST_1MIN_STA);
                //     }
                // }
                charg_offlie_cnt = 0;
                charg_finish_cnt = 0;
            }
            else{
                charg_finish_cnt ++;
                if(charg_finish_cnt >= 5){
                    // charging_online_cnt = 0;
                    if((CHARING_STA == get_sys_sta())||((ALING_CHARGE_STA == get_sys_sta())&&(sys_data.host_online_flag == 0))){
                        set_sys_sta(CHARGED_FINISH_STA);
                    }
                }
            }
       
        adc_pa1_read();
    }

    // 两个adc==0，代表离线
    if((adc_data.pa2_dac_buff[MAX_ADC_CNT/2] == 0)&&(adc_data.pa1_dac_buff[MAX_ADC_CNT/2]) == 0){
        if(IDLE_STA != get_sys_sta()){
            charg_offlie_cnt ++;
            if(charg_offlie_cnt > 15){
                set_sys_sta(IDLE_STA);
                charg_offlie_cnt = 0;
            }
            
        }
    }


#endif

}




void my_adc_init(void)
{

    adc_port_init();
    app_adc_init();

    // ADC_StartContinuousConversion(ADC);  //开启连续转换，每转换一次,产生EOC标志
      ///< 开启单次转换
    ADC_StartSingleConversion(ADC);  ///< 产生EOC标志

    // delay1ms(100);                           //延时100ms
    
   

}